﻿''' <summary>
''' This class Build View base on MetaQuery information
''' We will use this class to map SQL result to a View 
''' The view is a DataTable created, base on Visible Column
''' </summary>
''' <remarks></remarks>
Public Class MetaDataView

    Private _view As DataTable = Nothing

    ''' <summary>
    ''' Use to contains the Mapped values, from a Metaquery Result
    ''' The MetaQuery return a List of Type Tranformation
    ''' </summary>
    ''' <remarks></remarks>
    Private lookups As Dictionary(Of String, Dictionary(Of String, String))

    ''' <summary>
    ''' The name of the MetaQuery
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property QueryName As String
    Public Property SQLWhere As String
    Public Property MetaCommand As MetaQuery

    ''' <summary>
    ''' The ResultSet base on the Visible Column
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks>All ColumnName will be the Caption from the MetaQuery.MetaColumns</remarks>
    Public ReadOnly Property View As DataTable
        Get
            Return _view
        End Get
    End Property

    ''' <summary>
    ''' Result of a MetaQuery Statement
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ResultQuery As DataTable
    Public Sub New()
        lookups = New Dictionary(Of String, Dictionary(Of String, String))
    End Sub

    Public Sub New(ByVal queryName As String)
        Me.New()
        Me.QueryName = queryName
    End Sub

    ''' <summary>
    ''' Go get the MetaCommand so we can modify the SQL Statement
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub GetMetaCommand()
        MetaCommand = MetaQuery.GetMetaQueryByName(Me.QueryName)
    End Sub

    ''' <summary>
    ''' Construct a new DataTable base on visible metacolumns
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub BuildMetaView()
        Dim dt As DataTable
        'Dim colMq As DataColumn
        If MetaCommand Is Nothing Then
            GetMetaCommand()
        End If
        If MetaCommand IsNot Nothing Then
            If Me.ResultQuery Is Nothing Then
                If Not String.IsNullOrEmpty(Me.SQLWhere) Then
                    MetaCommand.SQLWhereContext = Me.SQLWhere
                End If
                MetaCommand.FillResultQuery()
                Me.ResultQuery = MetaCommand.ResultQuery.Copy()
            End If
            '
            dt = Me.ResultQuery.Copy()
        Else
            Throw New Exception("MetaQuery does not exist:" + Me.QueryName)
        End If
        _view = dt
    End Sub


    ''' <summary>
    ''' Rename ColumnName for Caption and Delete Invisible Columns
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub RestructureView()

        Dim colForMetaView As DataColumn
        Dim colVisible As Boolean
        For Each row As DataRow In MetaCommand.MetaColumns.Rows
            '
            colVisible = CBool(IIf(CInt(row("pVisible")) = 0, False, True))
            colForMetaView = _view.Columns(row("ColumnName").ToString)
            '
            If colVisible = True Then
                '
                If Not IsDBNull(row("pCaption")) Then
                    'colForMetaView.Caption = row("pCaption").ToString
                    colForMetaView.ColumnName = row("pCaption").ToString
                End If
                '
                'colForMetaView.ReadOnly = Not CBool(row("pLocked"))
                '
                If Not IsDBNull(row("pDataWidth")) AndAlso CInt(row("pDataWidth")) > 0 Then
                    colForMetaView.MaxLength = CInt(row("pDataWidth"))
                End If
            Else
                _view.Columns.Remove(colForMetaView)
            End If
        Next
    End Sub

    ''' <summary>
    ''' Insert the information in the view
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub FillView()
        If _view Is Nothing Then
            BuildMetaView()
        End If
        PrepareDataMapping()
        If lookups.Count > 0 Then
            TransformDataMapping()
        End If
        TransformDataRow()
        RestructureView()
    End Sub

    ''' <summary>
    ''' Replace the columns values from their corresponding Mapped Values contains in the Dictionary associate to the columns
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub TransformDataMapping()
        Dim lookup As Dictionary(Of String, String)
        Dim mapValues As KeyValuePair(Of String, Dictionary(Of String, String))
        Dim sourceValue As String
        'On each row...
        For Each row As DataRow In _view.Rows
            'On each Colomns with LOVs
            For Each mapValues In lookups
                lookup = mapValues.Value
                sourceValue = row(mapValues.Key).ToString
                'Change the value for it's mapping value
                If lookup.ContainsKey(sourceValue) Then
                    row.Table.Columns(mapValues.Key).ReadOnly = False
                    row(mapValues.Key) = lookup(sourceValue)
                End If
            Next
        Next
    End Sub

    Private Sub TransformDataRow()

    End Sub

    ''' <summary>
    ''' Go Get LOVs Code and Values and fill Dictionnary Collections
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub PrepareDataMapping()
        Me.MetaCommand.GetLOV_LKP()
        If Me.MetaCommand.HasLov Then
            BuildLookupsDictionaries(Me.MetaCommand.ListOfLov)
        End If
    End Sub

    ''' <summary>
    ''' Base on the LOVs we built Dictionnary collection so it's faster to transform later
    ''' </summary>
    ''' <param name="lovs">Dirtionary of ColumnName, Guid of MetaQuery</param>
    ''' <remarks></remarks>
    Private Sub BuildLookupsDictionaries(ByVal lovs As Dictionary(Of String, Guid))
        Dim lookup As Dictionary(Of String, String)
        'Scan the LOVs collection of the Metaquery
        For Each pair As KeyValuePair(Of String, Guid) In lovs
            Using mq As MetaQuery = MetaQuery.GetMetaQueryById(pair.Value)
                If mq IsNot Nothing Then
                    mq.FillResultQuery()
                    'Kept the results columns of the LOvs
                    If mq.ResultQuery.Rows.Count > 0 Then
                        lookup = New Dictionary(Of String, String)
                        For Each row As DataRow In mq.ResultQuery.Rows
                            lookup.Add(row("ValueCD").ToString, row("Value_EXT").ToString)
                        Next
                        lookups.Add(pair.Key, lookup)
                    End If
                End If
            End Using
        Next
    End Sub

    ''' <summary>
    ''' Go get the result from MetaQuery
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub FillResultQuery()
        Using mq As MetaQuery = MetaQuery.GetMetaQueryByName(Me.QueryName)
            If mq IsNot Nothing AndAlso Me.ResultQuery IsNot Nothing Then
                If Not String.IsNullOrEmpty(Me.SQLWhere) Then
                    MetaCommand.SQLWhereContext = Me.SQLWhere
                End If
                mq.FillResultQuery()
                Me.ResultQuery = mq.ResultQuery.Copy()
            Else
                Throw New Exception("MetaQuery does not exist:" + Me.QueryName)
            End If
        End Using
    End Sub



End Class
